#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:ouyang time:2022/10/27

import math as m
import socket
import json
import threading
import time
import base64
import torch
from torch import nn
from torchvision import datasets, transforms, models
from torch.utils.data import Dataset, DataLoader
from PIL import Image
import  numpy as np
import sys
import os
import io
import psutil
import copy
from collections import deque


class MainCarServer(threading.Thread):
    """
    所有新建的小车客户端连接都在这个类进行实例化
    """

    def __init__(self, conn):

        # 客户端连接初始化
        self.connect_sta = 0  # 客户端连接状态
        threading.Thread.__init__(self)

        self.thread_run = 1
        self.server = 0

        self.conn = conn

        self.connect_sta = 1

        self.json_buff = {}  # 缓存字典
        self.deal_data = {}  # 接收缓存
        self.get_offload_data = deque()  # 任务卸载的全部消息
        self.offload_body_data = deque()  # 任务卸载的内容信息
        self.offload_head_data = deque()  # 任务卸载头信息队列

        self.offload_all_data = deque()  # 存储所有的缓存信息
        self.temp_data_list = deque()  # 存储解析后的信息

        self.lock = threading.Lock()  # 获得线程锁
        self.read_head_lock = threading.Lock()  # 读写列表的线程锁
        self.read_body_lock = threading.Lock()  # 读写列表的线程锁

        self.pre_data = ''  # 接收缓存的记录

    def send_message(self, data):
        """
        传入Json格式数据
        当多个线程需要发送消息时，要上锁
        多线程是指， 一个线程发送头信息， 另一个线程发送任务信息
        :param data: 字典信息
        :return:
        """
        self.lock.acquire()

        send_data = '$'+data+'#'  # 把json格式转为字符串，添加帧头，以分辨每一帧的数据
        self.conn.send(send_data)
        time.sleep(0.001)  # 延时为经验值
        self.lock.release()
        # time.sleep(Send_delay_time)

    def rev_message(self):
        # 1024 指定从接收缓冲里最多读取多少字节
        data = self.conn.recv(4096)
        # print('self.json_buff:', self.json_buff)
        # 如果返回空bytes，表示对方关闭了连接
        # 退出循环，结束消息收发
        if not data:
            raise Exception
        else:
            return data

    def run(self):
        # 每个客户端的连接都会新建一个线程用于处理任务
        self.m_task()

    def m_task(self):
        while True:
            try:
                #
                if self.thread_run != 0:
                    self.offload_all_data.append(self.rev_message())

                else:
                    print("thread closed! ")
                    return 0
            except Exception as e:
                print(e)
                self.thread_close()
                return 0

    def get_connect_state(self):
        # 获取连接状态
        return self.connect_sta

    def thread_close(self):
        self.conn.close()  # 关闭一个客户端的连接
        # self.server.close()
        self.connect_sta = -1  # 连接状态变为断开状态
        self.thread_run = 0   # 线程结束状态

    def split_receive_data(self, receive_data):
        """
        用于分开接收到的粘连、断开的数据
        先找到开头的数据，
        :param receive_data: 传入接收的数据
        :return:
        """
        start_sta = receive_data.split('$')
        num = len(start_sta)
        for i in range(num):
            if start_sta[i] != '':
                stop_sta = start_sta[i].split('#')
                if len(stop_sta) == 2:
                    if self.pre_data == '':
                        self.temp_data_list.append(stop_sta[0])
                    else:
                        self.pre_data += stop_sta[0]
                        self.temp_data_list.append(self.pre_data)
                        self.pre_data = ''
                else:
                    self.pre_data += stop_sta[0]

    def classify_offloading_task(self):  # 根据接收信息分类项目

        count_1 = len(self.offload_all_data)
        if count_1 != 0:
            for i in range(0, count_1):
                temp_data = self.offload_all_data.popleft()
                self.split_receive_data(temp_data)

        count_2 = len(self.temp_data_list)
        if count_2 != 0:  # 每次在调用一次函数时，解析接收数据一次
            for i in range(0, count_2):
                deal_data = self.temp_data_list.popleft()
                if len(deal_data) > 10:

                    deal_data = json.loads(deal_data)  # json数据在这里进行解析

                    if deal_data.get('body', 0) != 0:
                        self.get_offload_data.append(deal_data)

    def get_offloading_data(self):  # 任务头信息接口， 返回的是一整个列表

        if len(self.get_offload_data) != 0:

            temp_list_data = copy.deepcopy(self.get_offload_data)
            self.get_offload_data.clear()

            return temp_list_data
        else:
            return []

    def get_thread_sta(self):
        return self.connect_sta
